#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Datetime: 2019/10/25 13:14
# @Author  : CHEN Wang
# @Site    :
# @File    : index_info.py
# @Software: PyCharm

"""
脚本说明: 获取指数基本信息
"""
import copy

from quant_researcher.quant.project_tool.logger.my_logger import LOG
from quant_researcher.quant.project_tool.db_operator import my_mysql, db_conn
from quant_researcher.quant.datasource_fetch.index_api.index_constant import SW_CODE_LIST, ZZ_CODE_LIST

T_INDEX_COMPONENTS = 'idx_components'
T_INDEX_INFO = 'idx_baseinfo'
T_SELF_BUILT_INDEX_INFO = 'mf_di_selfbenchmarkinfo'
T_INDEX_DAILY_RETURN = 'mf_di_idxdailyreturn'
T_AMAC_CSRC = 'mf_di_amac_and_csrc_relation'


def get_all_index_code():
    """
    得到所有的指数代码

    :return: list
    """
    conn = db_conn.get_basic_data_conn()
    select = f'distinct index_code'
    df = my_mysql.read_v2(select=select, sfrom=T_INDEX_INFO, conn=conn)
    ans = list(df['index_code'].values)
    conn.close()
    return ans


def get_sw_industry_name():
    """
    得到申万行业指数代码与名称的对应关系

    :return: pd.DataFrame
    """
    conn = db_conn.get_basic_data_conn()
    sql_str = ("select distinct c.index_code as industry_code, substr(i.index_sname, 1) as industry_name "
               f"from {T_INDEX_COMPONENTS} as c, {T_INDEX_INFO} as i "
               f"where c.index_code in {tuple(SW_CODE_LIST)}"
               "and c.index_code = i.index_code "
               "and left(c.secu_code,1) in ('3','6','0') ")
    sw_ind = my_mysql.read_v3(sql_str, conn)
    sw_ind['industry_name'] = sw_ind['industry_name'].str[2:]
    conn.close()
    return sw_ind


def get_index_name(index_code):
    """
    获取指数的名称。指数不像基金，应该没有需要获取所有指数的场景，所以暂时只支持传一个code

    :param str index_code: 指数代码
    :return: str
    """
    if index_code[:2] == 'TK':
        table = T_SELF_BUILT_INDEX_INFO
        conn = db_conn.get_basic_data_conn()
        select = 'benchmark_name'
        where = f"benchmark_code = '{index_code}'"
    else:
        table = T_INDEX_INFO
        conn = db_conn.get_derivative_data_conn()
        select = 'index_name'
        where = f"index_code = '{index_code}'"

    df = my_mysql.read_v2(
        select=select, where=where, sfrom=table, conn=conn
    )
    conn.close()

    if df.empty:
        LOG.error(f"没有找到{index_code}的名称，请检查输入")
        return
    index_name = df.iloc[0, 0]
    return index_name


def get_index_inception_date(index_code):
    """
    得到指数的净值开始日期

    :param str index_code: 指数代码
    :return: str 格式为带-字符串，'2010-08-20'
    """
    conn = db_conn.get_derivative_data_conn()
    nav_start_date = my_mysql.read_v2(select='min(day)', sfrom=T_INDEX_DAILY_RETURN,
                                      where=f"index_code = '{index_code}'", conn=conn)
    conn.close()

    nav_start_date = nav_start_date.iloc[0, 0]
    if nav_start_date is None:
        LOG.warning(f"没有找到{index_code}指数的净值信息")
    else:
        nav_start_date = str(nav_start_date)
    return nav_start_date


def get_amac_csrc_relation():
    """
    得到amac指数和证监会行业分类的对应关系

    :return: pd.DataFrame
                +------------+-----------+
                | index_code | csrc_code |
                +------------+-----------+
                |   H11030   |     A     |
                |   H11031   |     B     |
                |   H11041   |     D     |
                |   H11042   |     E     |
                |   H11043   |     G     |
                +------------+-----------+
    """
    conn = db_conn.get_derivative_data_conn()
    df = my_mysql.read_v2(select=['index_code', 'csrc_code'],
                          sfrom=T_AMAC_CSRC, conn=conn)
    conn.close()
    if df.empty:
        LOG.error(f"{T_AMAC_CSRC}表的数据为空，请检查")
        return
    return df


def get_index_needed_for_fitting(fitting_type, specific_type, **kwargs):
    """
    根据不同的拟合选取对应的指数

    :param str fitting_type: 拟合的类型，目前支持industry-行业；asset-资产；style-风格
    :param str specific_type: 每种拟合具体的类型
    :param kwargs:
            bool append_currency_index: 是否需要加入货币基金指数，默认True
    :return: list
    """
    append_currency_index = kwargs.pop('append_currency_index', True)
    if fitting_type == 'industry':
        if specific_type == 'ZZ10':
            index_needed_lst = copy.deepcopy(ZZ_CODE_LIST)
        else:
            index_needed_lst = copy.deepcopy(SW_CODE_LIST)
    elif fitting_type == 'bond_factors':
        index_needed_lst = []
    elif fitting_type in ['fama', 'barra']:
        index_needed_lst = []
    elif fitting_type == 'asset':
        index_needed_lst = [
            '000300',  # 沪深300
            'HSI',  # 恒生指数
            'CBA00301.CS',  # 中债总财富（总值）指数
            'AUCI'  # 黄金价格
        ]
    elif fitting_type == 'style':
        if specific_type == 'JC':
            index_needed_lst = [
                '399372', '399373', '399374', '399375', '399376', '399377'
            ]  # 巨潮风格指数
        elif specific_type == 'GZ':
            index_needed_lst = ['399370', '399371']  # 国证风格
        elif specific_type == 'SZ1000':
            index_needed_lst = ['399630', '399631']  # 深证1000
        else:
            raise NotImplementedError('目前只有：GZ，JC，SZ1000')
    else:
        raise NotImplementedError('目前只有：债券，fama，行业，风格，资产')
    if append_currency_index:
        # 不管是 中证行业 还是 申万行业，还是五花八门的风格指数 都加上货币指数
        index_needed_lst.append('H11025')
    LOG.info('找到的指数：%s', '，'.join(index_needed_lst))
    return index_needed_lst


def get_index_asset_allocation(index_code):
    """
    得到指数的资产配置信息

    :param str index_code: 指数代码
    :return: dict {'stock': 1, 'bond': 0, 'cash': 0, 'other': 0}
    """
    # 如果是自建混合指数，直接按照名称获得配置信息
    if index_code[:2] == 'TK':
        if index_code == 'TK50B50S':
            return {'stock': 0.5, 'bond': 0.5, 'cash': 0, 'other': 0}
        elif index_code == 'TK50B25S25H':
            return {'stock': 0.5, 'bond': 0.5, 'cash': 0, 'other': 0}
        elif index_code == 'TK90B10S':
            return {'stock': 0.1, 'bond': 0.9, 'cash': 0, 'other': 0}
        elif index_code == 'TK70B30S':
            return {'stock': 0.3, 'bond': 0.7, 'cash': 0, 'other': 0}
        elif index_code == 'TK30B70S':
            return {'stock': 0.7, 'bond': 0.3, 'cash': 0, 'other': 0}
        elif index_code == 'TK50S50H':
            return {'stock': 1, 'bond': 0, 'cash': 0, 'other': 0}
        elif index_code == 'TK80B15C05S':
            return {'stock': 0.05, 'bond': 0.95, 'cash': 0, 'other': 0}
        else:
            LOG.error(f"目前还没有{index_code}这个自建指数的信息，请检查")
            return
    else:
        # 如果不是自建指数，去指数信息表查找指数类别
        conn = db_conn.get_basic_data_conn()
        df = my_mysql.read_v2(select='index_type', sfrom=T_INDEX_INFO,
                              where=f"index_code = '{index_code}'", conn=conn)
        conn.close()
        if df.empty:
            LOG.error(f"没有找到{index_code}的信息，请检查")
            return
        index_type = df['index_type'].iloc[0]

        if index_type == '01':
            return {'stock': 1, 'bond': 0, 'cash': 0, 'other': 0}  # 股票指数
        elif index_type == '03':
            return {'stock': 0, 'bond': 1, 'cash': 0, 'other': 0}  # 债券指数
        elif index_type == '04':
            return {'stock': 0, 'bond': 0, 'cash': 0, 'other': 1}  # 期货指数
        elif index_code == 'H11025':
            return {'stock': 0, 'bond': 0, 'cash': 1, 'other': 0}  # 货币基金指数
        else:
            return {'stock': 1, 'bond': 0, 'cash': 0, 'other': 0}  # 默认股票指数


if __name__ == '__main__':
    # get_sw_industry_name()
    from quant_researcher.quant.project_tool import hammer

    # aaa = get_amac_csrc_relation()
    bbb = get_index_asset_allocation('000300')
    # hammer.slim(aaa.head(), a_f=1)
